package com.game.doudizhu.util;

import com.game.doudizhu.model.Card;
import com.game.doudizhu.service.CardService;

import java.util.*;
import java.util.stream.Collectors;

public class CardPatternUtil {

    public enum CardPattern {
        SINGLE,          // 单张
        PAIR,           // 对子
        TRIPLE,         // 三张
        TRIPLE_WITH_ONE, // 三带一
        TRIPLE_WITH_PAIR,// 三带对
        FOUR_WITH_TWO,   // 四带二
        FOUR_WITH_TWO_PAIRS, // 四带二对
        STRAIGHT,       // 顺子
        STRAIGHT_PAIR,  // 连对
        AIRPLANE,       // 飞机
        AIRPLANE_WITH_WINGS, // 飞机带翅膀
        BOMB,           // 炸弹
        ROCKET,         // 王炸
        INVALID         // 无效牌型
    }

    public static CardPattern getPattern(List<Card> cards) {
        if (cards == null || cards.isEmpty()) {
            return CardPattern.INVALID;
        }

        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));

        // 检查是否是王炸
        if (isRocket(cards)) {
            return CardPattern.ROCKET;
        }

        // 检查是否是炸弹
        if (isBomb(cards)) {
            return CardPattern.BOMB;
        }

        // 根据牌的数量判断可能的牌型
        switch (cards.size()) {
            case 1:
                return CardPattern.SINGLE;
            case 2:
                return isPair(cards) ? CardPattern.PAIR : CardPattern.INVALID;
            case 3:
                return isTriple(cards) ? CardPattern.TRIPLE : CardPattern.INVALID;
            case 4:
                return isTripleWithOne(cards) ? CardPattern.TRIPLE_WITH_ONE : CardPattern.INVALID;
            case 5:
                if (isTripleWithPair(cards)) return CardPattern.TRIPLE_WITH_PAIR;
                if (isStraight(cards)) return CardPattern.STRAIGHT;
                return CardPattern.INVALID;
            case 6:
                if (isFourWithTwo(cards)) return CardPattern.FOUR_WITH_TWO;
                if (isStraight(cards)) return CardPattern.STRAIGHT;
                if (isAirplane(cards)) return CardPattern.AIRPLANE;
                return CardPattern.INVALID;
            case 8:
                if (isFourWithTwoPairs(cards)) return CardPattern.FOUR_WITH_TWO_PAIRS;
                if (isStraightPair(cards)) return CardPattern.STRAIGHT_PAIR;
                if (isAirplane(cards)) return CardPattern.AIRPLANE;
                return CardPattern.INVALID;
            default:
                if (isStraight(cards)) return CardPattern.STRAIGHT;
                if (isStraightPair(cards)) return CardPattern.STRAIGHT_PAIR;
                if (isAirplane(cards)) return CardPattern.AIRPLANE;
                if (isAirplaneWithWings(cards)) return CardPattern.AIRPLANE_WITH_WINGS;
                return CardPattern.INVALID;
        }
    }

    public static boolean isGreaterThan(List<Card> cards1, List<Card> cards2) {
        CardPattern pattern1 = getPattern(cards1);
        CardPattern pattern2 = getPattern(cards2);

        // 如果牌型不同，只有炸弹和火箭可以比较
        if (pattern1 != pattern2) {
            if (pattern1 == CardPattern.ROCKET) return true;
            if (pattern2 == CardPattern.ROCKET) return false;
            if (pattern1 == CardPattern.BOMB && pattern2 != CardPattern.ROCKET) return true;
            if (pattern2 == CardPattern.BOMB && pattern1 != CardPattern.ROCKET) return false;
            return false;
        }

        // 获取主要牌值进行比较
        switch (pattern1) {
            case TRIPLE_WITH_ONE:
            case TRIPLE_WITH_PAIR:
            case AIRPLANE_WITH_WINGS:
                return getMaxWeightInTriples(cards1) > getMaxWeightInTriples(cards2);
            case FOUR_WITH_TWO:
            case FOUR_WITH_TWO_PAIRS:
                return getMaxWeightInFour(cards1) > getMaxWeightInFour(cards2);
            default:
                return getMaxWeight(cards1) > getMaxWeight(cards2);
        }
    }

    private static boolean isRocket(List<Card> cards) {
        if (cards.size() != 2) return false;
//        HashSet<String> set = new HashSet<>();
//        for (Card card : cards) {
//            if (card.getSuit() != Card.Suit.JOKER) return false;
//            set.add(card.getRank());
//        }
//        return set.size() == 2;
        return cards.stream()
                .filter(card -> card.getSuit() == Card.Suit.JOKER)
                .count() == 2 &&
                cards.stream()
                        .map(Card::getRank)
                        .collect(Collectors.toSet())
                        .containsAll(Arrays.asList("SMALL", "BIG"));
    }

    private static boolean isBomb(List<Card> cards) {
        if (cards.size() != 4) return false;
        String firstRank = cards.get(0).getRank();
        return cards.stream().allMatch(card -> card.getRank().equals(firstRank));
    }

    private static boolean isPair(List<Card> cards) {
        if (cards.size() != 2) return false;
        return cards.get(0).getRank().equals(cards.get(1).getRank());
    }

    private static boolean isTriple(List<Card> cards) {
        if (cards.size() != 3) return false;
        String firstRank = cards.get(0).getRank();
        return cards.stream().allMatch(card -> card.getRank().equals(firstRank));
    }

    private static boolean isTripleWithOne(List<Card> cards) {
        if (cards.size() != 4) return false;
        Map<String, Long> rankCount = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank, Collectors.counting()));
        return rankCount.containsValue(3L) && rankCount.containsValue(1L);
    }

    private static boolean isTripleWithPair(List<Card> cards) {
        if (cards.size() != 5) return false;
        Map<String, Long> rankCount = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank, Collectors.counting()));
        return rankCount.containsValue(3L) && rankCount.containsValue(2L);
    }

    private static boolean isStraight(List<Card> cards) {
        if (cards.size() < 5) return false;

        // 获取所有牌的权重并排序
        List<Integer> weights = cards.stream()
                .map(Card::getWeight)
                .sorted()
                .collect(Collectors.toList());

        // 检查是否是连续的
        for (int i = 1; i < weights.size(); i++) {
            if (weights.get(i) != weights.get(i - 1) + 1) {
                return false;
            }
        }

        // 不能包含2和大小王（权重大于14的牌）
        int maxWeight = Collections.max(weights);
        return maxWeight <= 14; // A的权重是14
    }

    private static boolean isStraightPair(List<Card> cards) {
        if (cards.size() < 6 || cards.size() % 2 != 0) return false;

        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));

        // 检查每个点数是否都是对子
        if (!rankGroups.values().stream().allMatch(list -> list.size() == 2)) {
            return false;
        }

        // 获取所有牌的权重并排序
        List<Integer> weights = rankGroups.values().stream()
                .map(list -> list.get(0).getWeight())
                .sorted()
                .collect(Collectors.toList());

        // 检查是否连续
        for (int i = 1; i < weights.size(); i++) {
            if (weights.get(i) != weights.get(i - 1) + 1) {
                return false;
            }
        }

        // 不能包含2和大小王
        int maxWeight = Collections.max(weights);
        return maxWeight <= 14;
    }

    private static boolean isAirplane(List<Card> cards) {
        if (cards.size() < 6 || cards.size() % 3 != 0) return false;

        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));

        // 获取所有三张的组合
        List<List<Card>> triples = rankGroups.values().stream()
                .filter(list -> list.size() == 3)
                .collect(Collectors.toList());

        // 至少需要两组三张
        if (triples.size() < 2) return false;

        // 获取三张的权重并排序
        List<Integer> weights = triples.stream()
                .map(list -> list.get(0).getWeight())
                .sorted()
                .collect(Collectors.toList());

        // 检查是否连续
        for (int i = 1; i < weights.size(); i++) {
            if (weights.get(i) != weights.get(i - 1) + 1) {
                return false;
            }
        }

        // 不能包含2和大小王
        int maxWeight = Collections.max(weights);
        return maxWeight <= 14;
    }

    private static boolean isAirplaneWithWings(List<Card> cards) {
        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));

        // 获取三张的组合
        List<List<Card>> triples = rankGroups.values().stream()
                .filter(list -> list.size() == 3)
                .collect(Collectors.toList());

        // 至少需要两组三张
        if (triples.size() < 2) return false;

        // 获取三张的权重并排序
        List<Integer> tripleWeights = triples.stream()
                .map(list -> list.get(0).getWeight())
                .sorted()
                .collect(Collectors.toList());

        // 检查三张是否连续
        for (int i = 1; i < tripleWeights.size(); i++) {
            if (tripleWeights.get(i) != tripleWeights.get(i - 1) + 1) {
                return false;
            }
        }

        // 检查翅膀数量是否正确（每组三张带一张或一对）
        int wingsCount = cards.size() - (triples.size() * 3);
        if (wingsCount != triples.size() && wingsCount != triples.size() * 2) {
            return false;
        }

        // 如果是带对子，检查翅膀是否都是对子
        if (wingsCount == triples.size() * 2) {
            long pairCount = rankGroups.values().stream()
                    .filter(list -> list.size() == 2)
                    .count();
            if (pairCount != triples.size()) {
                return false;
            }
        }

        // 不能包含2和大小王
        int maxWeight = Collections.max(tripleWeights);
        return maxWeight <= 14;
    }

    private static int getMaxWeight(List<Card> cards) {
        return cards.stream()
                .mapToInt(Card::getWeight)
                .max()
                .orElse(0);
    }

    // 拿到三带牌型中，三张牌部分最大的值
    private static int getMaxWeightInTriples(List<Card> cards) {
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));
        
        return rankGroups.entrySet().stream()
                .filter(entry -> entry.getValue().size() == 3)
                .map(entry -> entry.getValue().get(0).getWeight())
                .max(Integer::compareTo)
                .orElse(0);
    }

    public static void main(String[] args) {
        List<Card> cards = new ArrayList<>();
        cards.add(createCard(Card.Suit.HEARTS, "A", 14, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "A", 14, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "A", 14, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "K", 13, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "K", 13, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "K", 13, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "6", 6, 1L));
        cards.add(createCard(Card.Suit.HEARTS, "7", 7, 1L));
        System.out.println(getMaxWeightInTriples(cards));

    }

    private static Card createCard(Card.Suit suit, String rank, int weight, Long roomId) {
        Card card = new Card();
        card.setSuit(suit);
        card.setRank(rank);
        card.setWeight(weight);
        card.setRoomId(roomId);
        card.setStatus(Card.CardStatus.IN_DECK);
        return card;
    }

    private static boolean isFourWithTwo(List<Card> cards) {
        if (cards.size() != 6) return false;
        
        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));
        
        // 必须有一个四张的组合
        boolean hasFour = rankGroups.values().stream()
                .anyMatch(list -> list.size() == 4);
        
        // 剩下的两张可以是任意牌(可以相同也可以不同)
        return hasFour && cards.size() == 6;
    }

    private static boolean isFourWithTwoPairs(List<Card> cards) {
        if (cards.size() != 8) return false;
        
        // 按点数分组
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));
        
        // 必须有一个四张的组合
        boolean hasFour = rankGroups.values().stream()
                .anyMatch(list -> list.size() == 4);
        
        // 剩下的必须是两个对子
        boolean hasTwoPairs = rankGroups.values().stream()
                .filter(list -> list.size() == 2)
                .count() == 2;
        
        return hasFour && hasTwoPairs;
    }

    // 获取四带牌型中四张牌的权重
    private static int getMaxWeightInFour(List<Card> cards) {
        Map<String, List<Card>> rankGroups = cards.stream()
                .collect(Collectors.groupingBy(Card::getRank));
        
        return rankGroups.entrySet().stream()
                .filter(entry -> entry.getValue().size() == 4)
                .findFirst()
                .map(entry -> entry.getValue().get(0).getWeight())
                .orElse(0);
    }
} 